package net.moao.netutils_library.http;

import android.util.Log;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;

/**
 * HttpRequest
 *
 * @author Moao.Net
 * @DATE 2024/6/10
 */
public class HttpRequest {
    public static final String TAG = "HttpRequest";

    // 发起 GET 请求
    // 发起带有请求头的 GET 请求
    public static HttpResponse sendGetRequest(String url, Map<String, String> headers) throws Exception {
        URL obj = new URL(url);
        HttpURLConnection con = (HttpURLConnection) obj.openConnection();
        con.setRequestMethod("GET");

        // 添加请求头
        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                con.setRequestProperty(entry.getKey(), entry.getValue());
            }
        }

        int responseCode = con.getResponseCode();
        Log.d(TAG, "sendGetRequest: Sending 'GET' request to URL : " + url);
        Log.d(TAG, "sendGetRequest: Response Code : " + responseCode);

        // 读取响应体内容
        StringBuffer response = readBufferFromHttpURLConnection(con);
        // 打印响应体内容
        Log.d(TAG, "sendGetRequest: Response Body : " + response);
        return new HttpResponse(responseCode, con.getHeaderFields(), response);
    }

    // 发起 POST 请求
    public static HttpResponse sendPostRequest(String url, Map<String, String> headers, String body) throws Exception {
        // 创建 URL 对象
        URL obj = new URL(url);

        // 打开连接并强制转换为 HttpURLConnection
        HttpURLConnection con = (HttpURLConnection) obj.openConnection();

        // 设置请求方法为 POST
        con.setRequestMethod("POST");

        // 设置请求头，指定发送的内容类型为 JSON
        con.setRequestProperty("Content-Type", "application/json");

        // 添加请求头
        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                con.setRequestProperty(entry.getKey(), entry.getValue());
            }
        }

        // 允许输出，因为 POST 请求需要发送数据
        con.setDoOutput(true);

        // 获取输出流，用于发送请求体
        try (OutputStream os = con.getOutputStream()) {
            // 将 JSON 数据转换为字节数组，使用 UTF-8 编码
            byte[] input = body.getBytes("utf-8");

            // 将字节数组写入输出流
            os.write(input, 0, input.length);
        }

        // 获取 HTTP 响应码
        int responseCode = con.getResponseCode();

        // 打印请求信息和响应码
        Log.d(TAG, "sendPostRequest: Sending 'POST' request to URL : " + url);
        Log.d(TAG, "sendPostRequest: Post parameters : " + body);
        Log.d(TAG, "sendPostRequest: Response Code : " + responseCode);


        // 读取响应体内容
        StringBuffer response = readBufferFromHttpURLConnection(con);
        // 打印响应体内容
        Log.d(TAG, "sendPostRequest: Response Body : " + response);
        return new HttpResponse(responseCode, con.getHeaderFields(), response);
    }

    // 发起 PUT 请求
    public static HttpResponse sendPutRequest(String url, Map<String, String> headers, String body) throws Exception {
        URL obj = new URL(url);
        HttpURLConnection con = (HttpURLConnection) obj.openConnection();
        con.setRequestMethod("PUT");
        con.setRequestProperty("Content-Type", "application/json");

        // 添加请求头
        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                con.setRequestProperty(entry.getKey(), entry.getValue());
            }
        }

        con.setDoOutput(true);
        try (OutputStream os = con.getOutputStream()) {
            byte[] input = body.getBytes("utf-8");
            os.write(input, 0, input.length);
        }

        int responseCode = con.getResponseCode();
        Log.d(TAG, "sendPutRequest: Sending 'PUT' request to URL : " + url);
        Log.d(TAG, "sendPutRequest: Put parameters : " + body);
        Log.d(TAG, "sendPutRequest: Response Code : " + responseCode);

        // 读取响应体内容
        StringBuffer response = readBufferFromHttpURLConnection(con);
        // 打印响应体内容
        Log.d(TAG, "sendPutRequest: Response Body : " + response);
        return new HttpResponse(responseCode, con.getHeaderFields(), response);
    }

    // 发起 DELETE 请求
    public static HttpResponse sendDeleteRequest(String url, Map<String, String> headers, String body) throws Exception {
        URL obj = new URL(url);
        HttpURLConnection con = (HttpURLConnection) obj.openConnection();
        con.setRequestMethod("DELETE");

        // 添加请求头
        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                con.setRequestProperty(entry.getKey(), entry.getValue());
            }
        }

        int responseCode = con.getResponseCode();
        Log.d(TAG, "sendDeleteRequest: Sending 'DELETE' request to URL : " + url);
        Log.d(TAG, "sendDeleteRequest: Response Code : " + responseCode);

        // 读取响应体内容
        StringBuffer response = readBufferFromHttpURLConnection(con);
        // 打印响应体内容
        Log.d(TAG, "sendDeleteRequest: Response Body : " + response);
        return new HttpResponse(responseCode, con.getHeaderFields(), response);
    }


    /**
     * 从 HttpURLConnection 中 读取 响应体
     * @param con HttpURLConnection
     * @return 响应体(StringBuffer)
     * @throws IOException 打不开
     */
    public static StringBuffer readBufferFromHttpURLConnection(HttpURLConnection con) throws IOException {
        // 创建一个 StringBuilder 用于存储响应体内容
        StringBuffer response = new StringBuffer();
        // 尝试从输入流中读取响应体
        try (BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()))) {
            String inputLine;
            // 按行读取响应体内容
            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine);
            }
        } catch (Exception e) {
            // 如果发生异常（例如响应码不是 200），尝试从错误流中读取响应体
            try (BufferedReader in = new BufferedReader(new InputStreamReader(con.getErrorStream()))) {
                String inputLine;
                // 按行读取错误流内容
                while ((inputLine = in.readLine()) != null) {
                    response.append(inputLine);
                }
            }
        }
        return response;
    }
}
